package edu.java.homework.hw02;

public class StringHomework {

    /**
     * @param args
     */
    public static void main(String[] args) {
	// exer.01
	// "LaMq TriGlava, Убре Дебре"
	// "TOURIST"
	// String testString1 = "upperCaseCounter";
	String testString1 = null;
	System.out
		.println("upperCaseCounter: " + upperCaseCounter(testString1));

	// exer.02
	// "1634 Moskvich "
	// ""
	// "aha"
	// "123 sdfsdg;fd . df 124 ; 67 ;dsf.436"
	// String testString2="aha";
	// System.out.println("Count of digits in the string: " +
	// digitsCounter(testString2));
	// System.out.println("Count of digits in the string: " +
	// digitsCounter2(testString2));

	// //exer.03
	// //"UpII ta ta"
	// String testString3="mUshmoRok";
	// System.out.println("Count of vowels: " + vowelsCounter(testString3));
	// System.out.println("Count of vowels: " +
	// vowelsCounter2(testString3));

	// //exer.04
	// String
	// testString4="Jaba Kereritsa, kva: kva -->   \n kak \t taka. . \r ?";
	// printWords(testString4);

	// exer.05
	// "123s1""
	// "12345"
	// "a100sftr6gr:2"
	// "sadfr"
	// String testString5="13.3";
	// System.out.println("average: " + average(testString5));
	// System.out.println();
	// System.out.println("average: " + average2(testString5));

	// //exer.06
	// //"13.3"
	// //""
	// //
	// String testString6=" d\tdg\nsddf\\fsd\rds d ";
	// if(testString6.isEmpty()){
	// System.out.println("The string is empty.");
	// return;
	// }else{
	// char[] chArr= new char[testString6.length()];
	// chArr=toArr(testString6);
	// // for (char ch : chArr) {
	// // System.out.println("char: "+ ch);
	// // }
	// for(int iter=0; iter<chArr.length;iter++){
	// System.out.println("ch[" + iter + "]= " + chArr[iter]);
	// }
	//
	// }
	//	

	// //exer.07
	// //"zaska"
	// //"121"
	// //"1221"
	// //"jaaj"
	// //"\t \\\\ \t"
	// //"\t\t"
	// String testString7="";
	// System.out.println("string: "+ testString7);
	// System.out.println("The string is palendrom ? -->  " +
	// isPalindrom(testString7));

	// //exer.08
	// //""
	// //"ja132ba"
	// //"24424"
	// //"\t\\sofia123STZ.....\nfsd353"
	// //"reST"
	// String testString8="reST";
	// System.out.println("          string: "+ testString8);
	// System.out.println("new string-ver.1: " + removeDigits(testString8));
	// System.out.println("new string-ver.2: " +
	// removeDigits2(testString8));

	// //exer.09
	// //"reep"
	// //"bdu"
	// //""
	// //"1"
	// String testString9="1234";
	// System.out.println("         string: "+ testString9);
	// System.out.println("reversed string - ver.1: " +
	// reverse(testString9));
	// System.out.println("reversed string - ver.2: " +
	// reverse2(testString9));

	// //exer.10
	// //String testString10=replaceFirst("java, ligiteh bg", "lig", "log");
	// //String testString10=replaceFirst("java, ja none ligiteh bg", "ja",
	// "kva");
	// //String testString10=replaceFirst("", "lig", "log");
	// //String testString10=replaceFirst("java, ligiteh bg", "", "log");
	// String testString10=replaceFirst("java, that's is a nice java book",
	// "java", "C#");
	// System.out.println(testString10);

	// //exer.11
	// // String testString11=replaceLast1("Pala_abga_bg00", "bg", "US");
	// String testString11_1=replaceLast1("sad_USSAUS _aUStestME", "a",
	// "BG");
	// System.out.println("Result 1: "+ testString11_1);
	// // String testString11_2=replaceLast1("sad_USSAUS _aUStestME", "a",
	// "BG");
	// // System.out.println("Result 2: "+ testString11_2);
	// System.out.println(replaceLast2("tide me beep me", "me", "ME"));

	// //exer.12
	// String testString12=deleteFirst1("proverKaXX_lovko XX ovoz_oK",
	// "XX");
	// String testString12=deleteFirst1("XX", "XX");
	// String testString12=deleteFirst2("XXasaXX", "XX");
	// System.out.println(testString12);

	// //exer.13
	// String testString13=deleteLast2("Chihopei, chiKOchi", "KO");
	// System.out.println(testString13);

	// //exer.14
	// String[] strArr={"Astika", "Zagora", "Kamenitsa"};
	// System.out.println(concatStrings(strArr));

	// //exer.15
	// String[] strArr15={"albena", "aPriori", "gosho", "yanko"};
	// System.out.println("Decreasing? : " + isDecreasing(strArr15));

    }

    // Exer.01
    public static int upperCaseCounter(String inputString) {
	if (inputString == null || inputString.isEmpty()) {
	    return 0;
	}
	int counter = 0;
	for (int iter = 0; iter < inputString.length(); iter++) {
	    char currentChar = inputString.charAt(iter);
	    if (Character.isUpperCase(currentChar)) {
		counter++;
	    }
	}
	return counter;
    }

    // Exer.2
    /**
     * Counts the digits number in the input string.
     * 
     * @param inputString
     *            Input string fro method.
     * @return Returns the number of the digits in the input string.
     */
    public static int digitsCounter(String inputString) {
	// check for null first
	if (inputString.isEmpty()) {
	    return 0;
	}
	int counter = 0;
	for (int iter = inputString.length() - 1; iter >= 0; iter--) {
	    // perfect :)
	    switch (inputString.charAt(iter)) {
	    case '0':
	    case '1':
	    case '2':
	    case '3':
	    case '4':
	    case '5':
	    case '6':
	    case '7':
	    case '8':
	    case '9': {
		counter++;
		break;
	    }
	    }
	}
	return counter;
    }

    public static int digitsCounter2(String inputString) {
	// check for null first
	if (inputString.isEmpty()) {
	    return 0;
	}
	// better use counter like the previous method
	StringBuilder sb = new StringBuilder();
	// very good that you have used split, but be careful with the splitters
	// they are greedy for resources
	String[] digitSubstrings = inputString.split("[\\D]+");
	for (String subString : digitSubstrings) {
	    sb.append(subString);
	    // System.out.println(subString);
	}
	return sb.length();
    }

    // Exer.03
    public static int vowelsCounter(String inputString) {
	// check for null first
	if (inputString.isEmpty()) {
	    return 0;
	}
	int counter = 0;
	StringBuilder sb = new StringBuilder(inputString.toLowerCase());
	for (int iter = 0; iter < sb.length(); iter++) {
	    switch (sb.charAt(iter)) {
	    case 'a':
	    case 'o':
	    case 'e':
	    case 'i':
	    case 'u': {
		counter++;
	    }

	    }
	}
	return counter;
    }

    public static int vowelsCounter2(String inputString) {
	// check for null first
	if (inputString.isEmpty()) {
	    return 0;
	}
	int counter = 0;
	StringBuilder sb = new StringBuilder(inputString.length());
	char fictiveCharacter = '-';
	char replaceCharacter = '*';
	String tempString = inputString.replace(replaceCharacter,
		fictiveCharacter);
	tempString = tempString.replaceAll("[aoeuiAOEUI]", String
		.valueOf(replaceCharacter));
	// System.out.println(tempString);
	sb.append(tempString);
	for (int iter = 0; iter < sb.length(); iter++) {
	    if (sb.charAt(iter) == replaceCharacter) {
		counter++;
	    }
	}
	return counter;
    }

    // Exer.04
    // excellent
    public static void printWords(String inputString) {
	String[] words = inputString.split("[\\s]+");
	for (String word : words) {
	    System.out.println("echo: " + word);
	}
	System.out.println("Count of words in the sting: " + words.length);
    }

    // Exer.05
    public static boolean isDigit(char ch) {
	// if (ch == '0' || ch == '1' || ch == '2' || ch == '3' || ch == '4'
	// || ch == '5' || ch == '6' || ch == '7' || ch == '8'
	// || ch == '9') {
	// return true;
	// } else {
	// return false;
	// }

	// first possible optimization
	// boolean result = (ch == '0' || ch == '1' || ch == '2' || ch == '3'
	// || ch == '4' || ch == '5' || ch == '6' || ch == '7'
	// || ch == '8' || ch == '9');
	// return result;

	// second possible optimization
	// return (ch == '0' || ch == '1' || ch == '2' || ch == '3' || ch == '4'
	// || ch == '5' || ch == '6' || ch == '7' || ch == '8' || ch == '9');

	// third possible optimization
	return ('0' <= ch && ch <= '9');
    }

    // better use switch-case, i think it is faster...
    public static int convertToDigit(char ch) {
	// TODO do optimization with switch case
	// switch (ch) {
	// case '0': return 0;
	// case '1': return 1;
	//	    
	// break;
	//
	// default:
	// break;
	// }
	if (ch == '0') {
	    return 0;
	} else if (ch == '1') {
	    return 1;
	} else if (ch == '2') {
	    return 2;
	} else if (ch == '3') {
	    return 3;
	} else if (ch == '4') {
	    return 4;
	} else if (ch == '5') {
	    return 5;
	} else if (ch == '6') {
	    return 6;
	} else if (ch == '7') {
	    return 7;
	} else if (ch == '8') {
	    return 8;
	} else {
	    return 9;
	}
    }

    // TODO not working properly -> digits needed, not numbers
    public static double average(String inputString) {
	if (inputString.isEmpty()) {
	    return 0.0;
	}
	int number = 0;
	int sum = 0;
	int counter = 0;
	int countDigitsInNumber = 1;
	// we start to iterate over the chars in the sting from the end to the
	// beginning
	for (int iter = inputString.length() - 1; iter >= 0; iter--) {
	    char tmpChar = inputString.charAt(iter);
	    if (isDigit(tmpChar)) {
		int digit = convertToDigit(tmpChar);
		number = number + countDigitsInNumber * digit;
		countDigitsInNumber *= 10;
		if (iter == 0) { // if we reach to the first char of the string
		    sum += number;
		    counter++;
		}
	    } else {
		sum += number;
		number = 0;

		if (countDigitsInNumber != 1) {
		    counter++;
		}
		countDigitsInNumber = 1;
	    }
	}
	if (counter == 0) {
	    return 0.0;
	} else {
	    return (sum * 1.0) / counter;
	}
    }

    // TODO not working properly -> digits needed, not numbers
    public static double average2(String inputString) {
	if (inputString.isEmpty()) {
	    return 0.0;
	}
	int sum = 0;
	String[] numbers = inputString.split("[\\D]+");
	if (numbers.length == 0) {
	    return 0.0;
	}
	for (String number : numbers) {
	    int numb = (Integer.valueOf(number)).intValue();
	    sum += numb;
	}
	return (sum * 1.0) / (numbers.length);
    }

    // Exer.06
    // perfect
    public static char[] toArr(String inputString) {
	char[] charsArray = new char[inputString.length()];
	for (int iter = 0; iter < inputString.length(); iter++) {
	    charsArray[iter] = inputString.charAt(iter);
	}
	return charsArray;

    }

    // Exer.07
    // great :)
    public static boolean isPalindrom(String inputString) {
	int iter = 0;
	int length = inputString.length();
	while (iter != ((length + 1) / 2)) {
	    if (inputString.charAt(iter) != inputString.charAt(length - iter
		    - 1)) {
		return false;
	    }
	    iter++;
	}
	return true;
    }
    
    // TODO exer.07 with recursion

    // Exer.08
    // bravo
    public static String removeDigits(String inputString) {
	// first check for null
	if (inputString.isEmpty()) {
	    return inputString;
	}
	StringBuilder sb = new StringBuilder();
	String[] strArr = inputString.split("[\\d]+");
	for (String str : strArr) {
	    sb.append(str);
	}
	return sb.toString();
    }

    // hehe :D tricky and elegant
    public static String removeDigits2(String inputString) {
	return inputString.replaceAll("[\\d]", "");
    }

    // exer. 09
    // faster and memory-economic solution, but not object oriented
    public static String reverse(String inputString) {
	// first check for null
	if (inputString.isEmpty()) {
	    return inputString;
	}

	char[] chars = inputString.toCharArray();
	int index = 0;
	int length = chars.length;
	while (index != ((length + 1) / 2)) {
	    char ch = chars[length - index - 1];
	    chars[length - index - 1] = chars[index];
	    chars[index] = ch;
	    index++;
	}
	return new String(chars);
    }

    // may be not so optimal but object-oriented solution. very good!
    public static String reverse2(String inputString) {
	// first check for null
	if (inputString.isEmpty()) {
	    return inputString;
	}

	StringBuilder sb = new StringBuilder(inputString.length());
	for (int index = inputString.length() - 1; index >= 0; index--) {
	    sb.append(inputString.charAt(index));
	}
	return sb.toString();
    }

    // exer.10

    public static String replaceFirst(String input, String s1, String s2) {
	// first check for null
	if (input.isEmpty()) {
	    return null;
	}
	if (s1.isEmpty()) {
	    return input;
	}
	if (input.indexOf(s1) == -1) {
	    return null;
	}
	// first way
	// int grooveIndex=input.indexOf(s1) + s1.length();
	// String firstSubString=input.substring(0, grooveIndex);
	// String secondSubString=input.substring(grooveIndex);
	// StringBuilder sb= new StringBuilder();
	// sb.append(firstSubString.replace(s1, s2)).append(secondSubString);
	// return sb.toString();

	// second way
	int grooveIndex1 = input.indexOf(s1);
	// int grooveIndex2 = input.indexOf(s1) + s1.length(); // correct but
	// you can reuse the grooveIndex1 instead to call the method indexOf()
	// again
	int grooveIndex2 = grooveIndex1 + s1.length();

	// perfect :)
	StringBuilder sb2 = new StringBuilder();
	sb2.append(input.substring(0, grooveIndex1)).append(s2).append(
		input.substring(grooveIndex2));
	return sb2.toString();

    }

    // exer.11
    public static String replaceLast1(String input, String s1, String s2) {
	if (input.isEmpty()) {
	    return input;
	}
	if (s1.isEmpty()) {
	    return input;
	}

	if (input.lastIndexOf(s1) == -1) {
	    return null;
	}
	StringBuilder resSB = new StringBuilder();
	int grooveIndex1 = input.lastIndexOf(s1);

	// very good (in relation to the usage of grooveIndex1) ;)
	int grooveIndex2 = grooveIndex1 + s1.length();
	String firstSubString = input.substring(0, grooveIndex1);
	String secondSubString = input.substring(grooveIndex2);
	resSB.append(firstSubString).append(s2).append(secondSubString);
	return resSB.toString();
    }

    public static String replaceLast2(String input, String s1, String s2) {
	if (input.isEmpty()) {
	    return input;
	}
	if (s1.isEmpty()) {
	    return input;
	}

	if (input.lastIndexOf(s1) == -1) {
	    return null;
	}

	StringBuilder sbInput = new StringBuilder(input);
	StringBuilder sbString1 = new StringBuilder(s1);
	StringBuilder sbString2 = new StringBuilder(s2);
	String revInput = sbInput.reverse().toString();
	String revString1 = sbString1.reverse().toString();
	String revString2 = sbString2.reverse().toString();

	StringBuilder result = new StringBuilder();
	result.append(replaceFirst(revInput, revString1, revString2));
	return result.reverse().toString();

    }

    // TODO -> as homework, implement this method, but using the
    // String#substring();
    public static String replaceLast3(String input, String s1, String s2) {
	// implmenet me :)
	return null;
    }

    // exer.12
    // lovely! :D
    public static String deleteFirst1(String input, String s1) {
	// first check for null
	if (input.isEmpty()) {
	    return input;
	}
	if (s1.isEmpty()) {
	    return input;
	}
	if (input.indexOf(s1) == -1) {
	    return null;
	}
	int grooveIndex1 = input.indexOf(s1);
	int grooveIndex2 = input.indexOf(s1) + s1.length();
	String beginString = input.substring(0, grooveIndex1);
	String remainderString = input.substring(grooveIndex2);
	return beginString + remainderString;
    }

    public static String deleteFirst2(String input, String s1) {
	return replaceFirst(input, s1, "");
    }

    // exer.13
    // very good
    public static String deleteLast1(String input, String s1) {
	// first check for null
	if (input.isEmpty()) {
	    return input;
	}
	if (s1.isEmpty()) {
	    return input;
	}
	if (input.lastIndexOf(s1) == -1) {
	    return null;
	}
	int grooveIndex1 = input.lastIndexOf(s1);
	int grooveIndex2 = input.lastIndexOf(s1) + s1.length();
	String firstSubstring = input.substring(0, grooveIndex1);
	String secondSubstring = input.substring(grooveIndex2);
	return firstSubstring + secondSubstring;
    }

    // great
    public static String deleteLast2(String input, String s1) {
	return replaceLast2(input, s1, "");
    }

    // exer.14
    // marvellous
    public static String concatStrings(String[] inputStrings) {
	// TODO check first for null
	StringBuilder result = new StringBuilder();
	for (String str : inputStrings) {
	    result.append(str);
	}
	return result.toString();
    }

    // exer.15
    // very good
    // TODO javadoc
    public static boolean isDecreasing(String[] inputStrings) {
	// TODO check first for null
	if (inputStrings.length < 2) {
	    throw new IllegalArgumentException("Incorrect array of Strings");
	}

	// for (int index = 0; index <= (inputStrings.length - 2); index++) {
	// proposition for optimization -> in that way you save redundant
	// substractions:
	for (int index = 0, n = (inputStrings.length - 2); index <= n; index++) {
	    int compareStatus = inputStrings[index]
		    .compareTo(inputStrings[index + 1]);
	    if (compareStatus > 0) {
		return false;
	    }
	}
	return true;
    }
}
